#include "index_string.h"
//# define DEBUG_LEVEL 19
//# define DEBUG_LEVEL 19
#include "debug_func.h"
#include "string_hash.h"
#include <ext/hash_map>


using std::string;
using std::deque;


//
//	pimpl implementation class
//

typedef __gnu_cxx::hash_map<string, unsigned, hash_string> t_map_str_uint;
class t_index_string::impl
{

    // private data

public:
	t_map_str_uint				name_to_index;
	std::deque<std::string>		names;
	unsigned					size() const {return names.size();}
	
    impl(impl const & other):
        name_to_index(other.name_to_index),
        names(other.names)
    {
    }

    impl & operator=(impl const & other )
    {
        name_to_index = other.name_to_index;
        names = other.names;
        return *this;
    }

    impl(unsigned default_size)
	{
		// reserve hash map size
		if (default_size)
			name_to_index.resize(default_size);
	}
    ~impl(){}
	

	
	unsigned index(const std::string& name, bool& added)
	{
		// if name is already there
		t_map_str_uint::iterator p_index = name_to_index.find(name);
		if (p_index != name_to_index.end())
		{
			added = false;
			return (p_index->second);
		}

		// name is new
		unsigned index = names.size();
		names.push_back(name);
		name_to_index[names.back().c_str()] = index;
		added = true;
		return index;
	}

	bool is_indexed(const std::string& name, unsigned& index) const
	{
		t_map_str_uint::const_iterator p_index = name_to_index.find(name);
		if (p_index != name_to_index.end())
		{
			index = p_index->second;
			return true;
		}
		return false;
	}
};



//
//	forwarding functions
//
bool t_index_string::is_indexed(const std::string& name, unsigned& i) const
{
	return pimpl_->is_indexed(name, i);
}
unsigned t_index_string::index(const std::string& name)
{
	bool added;
	return pimpl_->index(name, added);
}

t_index_string & t_index_string::operator=(t_index_string const & other)
{
    *pimpl_ = *(other.pimpl_);
    return *this;
}

t_index_string::t_index_string(unsigned default_size)
: pimpl_(new impl(default_size))
{}

t_index_string::t_index_string(const t_index_string& other)
: pimpl_(new impl(*other.pimpl_))
{
}



unsigned t_index_string::index(const std::string& name, bool& added)
{
	return pimpl_->index(name, added);
}

// unsafe because index no longer in synch
//  need to rebuild from scratch
//void t_index_string::swap_deque(std::deque<std::string>& new_deque)
//{
//	new_deque.swap(pimpl_->names);
//}

const std::deque<std::string>&	t_index_string::get_deque() const
{
	return pimpl_->names;
}

	
	
unsigned t_index_string::size() const
{
	return pimpl_->size();
}

